/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ru.rantipin.GUI;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import ru.rantipin.utilities.ConnectionDataBaseListner;
import ru.rantipin.persistence.PersistenceHelper;

/**
 *
 * @author rantipin
 */
public class DataBaseConnectionDialog extends JDialog {
    
    final static private String TITLE = "DataBase connection settings";
    final static private String ICON = "/images/setting.png"; 
    
    public DataBaseConnectionDialog(JFrame main, ConnectionDataBaseListner listner) {
        setTitle(TITLE);
        
        this.listner = listner;
        
        ImageIcon icon = new ImageIcon(getClass().getResource(ICON));
        setIconImage(icon.getImage());
        
        setModal(true);
        setSize(350, 200);
        setResizable(false);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);
                isActive = false;
            }
        });
        
        setLocationRelativeTo(main);
        
        initComponentsLayout();
        
        setVisible(true);
    }
    
    private void initComponentsLayout() {
        GridBagLayout gridbag = new GridBagLayout();
        setLayout(gridbag);
        
        KeyAdapter keyAdapter = new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
                getButtonOK().setEnabled(false);
            }
            
        };
        userNameText.addKeyListener(keyAdapter);
        passwordText.addKeyListener(keyAdapter);
        connectionURLText.addKeyListener(keyAdapter);
                
        gridbag.setConstraints(userNameLabel, 
                new GridBagConstraints(
                    0, 0,
                    1, 1,
                    0.0, 0.0,
                    GridBagConstraints.LINE_START, GridBagConstraints.NONE,
                    new Insets(10, 10, 0, 10),
                    0, 0
                ));
        add(userNameLabel);
        
        gridbag.setConstraints(userNameText, 
                new GridBagConstraints(
                    1, 0,
                    GridBagConstraints.REMAINDER, 1,
                    1.0, 0.0,
                    GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL,
                    new Insets(10, 10, 0, 10),
                    0, 0
                ));
        add(userNameText);
        
        gridbag.setConstraints(passwordLabel, 
                new GridBagConstraints(
                    0, 1,
                    1, 1,
                    0.0, 0.0,
                    GridBagConstraints.LINE_START, GridBagConstraints.NONE,
                    new Insets(10, 10, 0, 10),
                    0, 0
                ));
        add(passwordLabel);
        
        gridbag.setConstraints(passwordText, 
                new GridBagConstraints(
                    1, 1,
                    GridBagConstraints.REMAINDER, 1,
                    1.0, 0.0,
                    GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL,
                    new Insets(10, 10, 0, 10),
                    0, 0
                ));
        add(passwordText);
        
        gridbag.setConstraints(connectionURLLabel, 
                new GridBagConstraints(
                    0, 2,
                    1, 1,
                    0.0, 0.0,
                    GridBagConstraints.LINE_START, GridBagConstraints.NONE,
                    new Insets(10, 10, 0, 10),
                    0, 0
                ));
        add(connectionURLLabel);
        
        gridbag.setConstraints(connectionURLText, 
                new GridBagConstraints(
                    1, 2,
                    GridBagConstraints.REMAINDER, 1,
                    1.0, 0.0,
                    GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL,
                    new Insets(10, 10, 0, 10),
                    0, 0
                ));
        add(connectionURLText);
        
        gridbag.setConstraints(getProgressBar(), 
                new GridBagConstraints(
                    0, 3,
                    GridBagConstraints.REMAINDER, 1,
                    1.0, 0.0,
                    GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL,
                    new Insets(10, 10, 0, 10),
                    0, 0
                ));
        add(getProgressBar());
        
        
        gridbag.setConstraints(getButtonTest(), 
                new GridBagConstraints(
                    0, 4,
                    1, 1,
                    0.0, 0.0,
                    GridBagConstraints.LAST_LINE_START, GridBagConstraints.NONE,
                    new Insets(10, 10, 10, 10),
                    0, 0
                ));
        add(getButtonTest());
        
        gridbag.setConstraints(getButtonOK(), 
                new GridBagConstraints(
                    1, 4,
                    1, 1,
                    1.0, 1.0,
                    GridBagConstraints.LAST_LINE_END, GridBagConstraints.NONE,
                    new Insets(10, 0, 10, 10),
                    0, 0
                ));
        add(getButtonOK());
        
        gridbag.setConstraints(getButtonCancel(), 
                new GridBagConstraints(
                    2, 4,
                    1, 1,
                    0.0, 0.0,
                    GridBagConstraints.LAST_LINE_END, GridBagConstraints.NONE,
                    new Insets(10, 0, 10, 10),
                    0, 0
                ));
        add(getButtonCancel());
    }
    
    private void validation() throws Exception {
        if (userNameText.getText().equals("")) {
            throw new Exception("User name should not be empty");
        }
        
        if (passwordText.getPassword().length == 0) {
            throw new Exception("Password and ConfirmPassword should equals and not be empty");
        }
            
        Pattern p = Pattern.compile("//[-\\w_.]+:[\\d]+/[-\\w_.]+");
        Matcher m = p.matcher(connectionURLText.getText());
        if (!m.matches()) {
            throw new Exception("Invalid connection url");
        }
    }
    
    private JButton getButtonOK() {
        if (buttonOK == null) {
            buttonOK = new JButton("OK");
            buttonOK.setEnabled(false);
            buttonOK.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    PersistenceHelper.getInstance().initializeEntityManager(
                            userNameText.getText(), 
                            new String(passwordText.getPassword()), 
                            connectionURLText.getText());
                    
                    listner.connectionEsteblished();
                    dispose();
                }
            });
        }
        
        return buttonOK;
    }
    
    private JButton getButtonCancel() {
        if (buttonCancel == null) {
            buttonCancel = new JButton("Cancel");
            buttonCancel.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    isActive = false;
                    dispose();
                }
            });
        }
        
        return buttonCancel;
    }
    
    private JButton getButtonTest() {
        if (buttonTest == null) {
            buttonTest = new JButton("Test");
            buttonTest.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    try {
                        isActive = true;
                        validation();
                        
                        new Thread(new Runnable() {
                            public void run() {
                                try {
                                    if (isActive) {
                                        SwingUtilities.invokeLater(new Runnable() {
                                            public void run() {
                                                getProgressBar().setVisible(true);
                                                buttonTest.setEnabled(false);
                                            }
                                        });
                                    }
                                    
                                    Thread.sleep(3000);
                                    PersistenceHelper.getInstance().testConnection(
                                            userNameText.getText(), 
                                            new String(passwordText.getPassword()), 
                                            connectionURLText.getText());
                                    
                                    if (isActive == true) {
                                        SwingUtilities.invokeLater(new Runnable() {
                                            public void run() {
                                                JOptionPane.showMessageDialog(DataBaseConnectionDialog.this, "Connection successfully established", 
                                                    "Connection test information", JOptionPane.INFORMATION_MESSAGE);
                                                getButtonOK().setEnabled(true);
                                            }
                                        });
                                    }
                                    
                                } catch (SQLException ex) {
                                    if (isActive) {
                                        SwingUtilities.invokeLater(new Runnable() {
                                            public void run() {
                                                JOptionPane.showMessageDialog(DataBaseConnectionDialog.this, "Conection test failed: Can't create connection with DB", 
                                                    "Connection test warning", JOptionPane.WARNING_MESSAGE);
                                            }
                                        });
                                    }
                                    Logger.getLogger(DataBaseConnectionDialog.class.getName()).log(Level.WARNING, null, ex);
                                } catch (InterruptedException ex) {
                                    Logger.getLogger(DataBaseConnectionDialog.class.getName()).log(Level.SEVERE, null, ex);
                                } finally {
                                    if (isActive) {
                                        SwingUtilities.invokeLater(new Runnable() {
                                            public void run() {
                                                buttonTest.setEnabled(true);
                                                getProgressBar().setVisible(false);
                                            }
                                        });
                                    }
                                }
                            }
                        }).start();
                        
                    } catch(Exception ex) {
                        JOptionPane.showMessageDialog(DataBaseConnectionDialog.this, "Conection test failed: " + ex.getMessage(), 
                            "Connection test warning", JOptionPane.WARNING_MESSAGE);
                    }
                }
            });
        }
        
        return buttonTest;
    }
    
    private JProgressBar getProgressBar() {
        if (progress == null) {
            progress = new JProgressBar();
            progress.setIndeterminate(true);
            progress.setVisible(false);
        }
        
        return progress;
    }
    
    private ConnectionDataBaseListner listner = null;
    
    private volatile boolean isActive = true;
    private JProgressBar progress = null;
    
    private JLabel userNameLabel = new JLabel("UserName:");
    private JLabel passwordLabel = new JLabel("Password:");
    private JLabel connectionURLLabel = new JLabel("Connection URL:");
    
    private JTextField userNameText = new JTextField();
    private JPasswordField passwordText = new JPasswordField();
    private JTextField connectionURLText = new JTextField();
    
    private JButton buttonOK = null;
    private JButton buttonCancel = null;
    private JButton buttonTest = null;
}
